use crate::exchange::lbank::rest::TICKER_STEP;
use crate::exchange::lib::{CONFIG, TICKER, Ticker, callback};
use crate::utils::{
    WRITE_BUFFER_SIZE, create_text_frame, parse_frame_with_compression, start_ws_with_compression,
};
use sonic_rs::{JsonValueTrait, json, pointer};
use std::sync::Arc;
use std::time::Duration;
use tokio::io::{AsyncWriteExt, BufWriter};

pub async fn ws(symbols: Arc<Vec<String>>) {
    loop {
        let (mut rx, tx, mut deflate) = start_ws_with_compression(
            "uuws.rerrkvifj.com",
            Some("/ws/v3"),
            None,
            CONFIG.proxy.as_str(),
            11,
            11,
        )
        .await;

        let mut buf_writer = BufWriter::with_capacity(WRITE_BUFFER_SIZE, tx);

        let symbol = &symbols[0];

        println!("Lbank只能订阅一个交易对, 因为在响应中是不返回交易对信息的");

        let msg = json!({
            "x":3,
            "y":"3000000001",
            "a":{
                "i": format!(
            "{}_{}_25",
            symbol,
            TICKER_STEP.get().unwrap().get(symbol).unwrap()
        )
            },
            "z":1
        });
        let msg = create_text_frame(msg.to_string().as_str());
        buf_writer.write_all(&msg).await.unwrap();
        buf_writer.flush().await.unwrap();

        tokio::spawn(async move {
            let mut interval = tokio::time::interval(Duration::from_secs(5));
            loop {
                interval.tick().await;
                let ping_frame = create_text_frame("ping");

                if buf_writer.write_all(&ping_frame).await.is_err() {
                    break;
                }
                if buf_writer.flush().await.is_err() {
                    break;
                }
            }
        });

        loop {
            let (_, payload) = parse_frame_with_compression(&mut rx, &mut deflate)
                .await
                .unwrap();

            // "pong"
            if payload.len() == 4 {
                continue;
            }

            let ask: f64 = unsafe {
                sonic_rs::get_from_slice_unchecked(&payload, pointer!["s", 0, 0]).unwrap()
            }
            .as_str()
            .unwrap()
            .parse()
            .unwrap();
            let ask_amount: f64 = unsafe {
                sonic_rs::get_from_slice_unchecked(&payload, pointer!["s", 0, 1]).unwrap()
            }
            .as_str()
            .unwrap()
            .parse()
            .unwrap();

            let bid: f64 = unsafe {
                sonic_rs::get_from_slice_unchecked(&payload, pointer!["b", 0, 0]).unwrap()
            }
            .as_str()
            .unwrap()
            .parse()
            .unwrap();
            let bid_amount: f64 = unsafe {
                sonic_rs::get_from_slice_unchecked(&payload, pointer!["b", 0, 1]).unwrap()
            }
            .as_str()
            .unwrap()
            .parse()
            .unwrap();

            let timestamp =
                unsafe { sonic_rs::get_from_slice_unchecked(&payload, pointer!["w"]).unwrap() }
                    .as_i64()
                    .unwrap();

            let mut value = TICKER
                .entry(symbol.clone())
                .or_insert_with(|| Ticker::default());

            value.coinex = (bid, ask);
            value.coinex_timestamp = timestamp;
            value.coinex_bid_amount = bid_amount;
            value.coinex_ask_amount = ask_amount;

            drop(value);

            callback(symbol.to_string()).await;
        }
    }
}
